﻿namespace Blaze.Editor.Dev
{
    using System;
    using System.Linq;
    using System.Reflection;
    using UnityEditor;
    using UnityEngine;

    /// <summary>
    /// 开发用的功能窗口管理类。
    /// </summary>
    public class DevWindow : EditorWindow
    {
        /// <summary>
        /// 获取<see cref="DevWindow"/>的唯一实例。
        /// </summary>
        public static DevWindow Instance { get; private set; }

        /// <summary>
        /// 显示开发面板窗口。
        /// </summary>
        [MenuItem("Blaze/面板/开发面板 &F7", false, BlazeEditorMenu.Priority.Panels)]
        public static void ShowWindow()
        {
            if (Instance == null)
                Instance = GetWindow<DevWindow>();

            var content = new GUIContent
            {
                text = "开发面板",
                image = BlazeEditorResources.Load<Texture2D>("icon_dev.png")
            };
            Instance.titleContent = content;
            Instance.Show();
        }

        /// <summary>
        /// 获取所有的开发功能面板。
        /// </summary>
        /// <returns></returns>
        protected DevPanel[] GetDevPanels()
        {
            var testPanelType = typeof (DevPanel);
            var query = from type in Assembly.GetExecutingAssembly().GetTypes()
                where testPanelType.IsAssignableFrom(type) && !type.IsAbstract
                let panel = (DevPanel) Activator.CreateInstance(type)
                orderby panel.Priority, panel.Name
                select panel;
            return query.ToArray();
        }

        protected void OnDisable()
        {
            mIsInitialized = false;
            EditorApplication.update -= OnUpdate;
        }

        protected void OnEnable()
        {
            mDevPanels = GetDevPanels();
            foreach (var panel in mDevPanels)
                panel.Window = this;
            mIsInitialized = true;
            EditorApplication.update += OnUpdate;
        }

        protected void OnGUI()
        {
            if (EditorApplication.isCompiling)
            {
                ShowNotification(mCompilingContent);
                return;
            }

            if (!mIsInitialized)
                return;
            if (mDevPanels.Length == 0)
                return;

            EditorGUILayout.BeginHorizontal();

            EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(72));
            EditorGUILayout.BeginVertical();
            for (var i = 0; i < mDevPanels.Length; i++)
            {
                GUI.color = i == mCurrentPanelIndex ? Color.green : Color.white;
                if (GUILayout.Button(mDevPanels[i].Name, GUILayout.Height(36), GUILayout.MaxWidth(72)))
                    selectPanel(i);
            }
            EditorGUILayout.EndVertical();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(8);

            EditorGUILayout.BeginVertical();
            mScrollPosition = EditorGUILayout.BeginScrollView(mScrollPosition, false, false);
            GUILayout.Space(8);
            GUI.color = Color.white;
            if (mCurrentPanelIndex < 0)
            {
                mCurrentPanelIndex = 0;
            }
            else
            {
                mDevPanels[mCurrentPanelIndex].Update();
            }
            GUILayout.EndArea();
            EditorGUILayout.EndVertical();

            EditorGUILayout.EndHorizontal();
            EditorGUILayout.EndHorizontal();
        }

        protected void OnUpdate()
        {
            if (!mIsInitialized || EditorApplication.isCompiling)
                return;
            if (mCurrentPanelIndex >= mDevPanels.Length || mCurrentPanelIndex < 0)
                return;
            mDevPanels[mCurrentPanelIndex].OnUpdate();
        }

        private void selectPanel(int index)
        {
            if (mCurrentPanelIndex == index)
                return;

            if (mCurrentPanelIndex >= 0)
                mDevPanels[mCurrentPanelIndex].OnDisable();
            mCurrentPanelIndex = index;
            mDevPanels[mCurrentPanelIndex].OnEnable();
        }

        private readonly GUIContent mCompilingContent = new GUIContent("正在编译...请稍候");
        private int mCurrentPanelIndex = -1;
        private DevPanel[] mDevPanels;
        private bool mIsInitialized;
        private Vector2 mScrollPosition;
    }
}